#pragma once
#include "Connection.hpp"


class HandleConnection
{
public:
    HandleConnection(func_t func)
        :_func(func)
    {}

    void HandleRecv(Connection* conn)
    {
        errno = 0;

        int fd = conn->GetSockfd();
        LOG(INFO, "HandleRecv, fd: %d...\n", fd);

        char buffer[1024];
        while(true)
        {
            ssize_t n = recv(fd, buffer, sizeof(buffer) - 1, 0);
            if(n > 0)
            {
                buffer[n] = '\0';
                conn->AppendInbuffer(buffer);
                LOG(INFO, "client say# %s\n", buffer);
            }
            // else if(n == 0)
            // {

            //     close(fd);
            //     break;
            // }
            else  
            {
                if(errno == EWOULDBLOCK || errno == EAGAIN)
                {
                    // 非阻塞，说明读完了
                    break;
                }
                else if(errno == EINTR)
                {
                    // 被信号干扰
                    continue;
                }
                else
                {
                    LOG(INFO, "exec excepter\n");
                    // 出错由 conn 中的_except处理异常
                    conn->_excepter(conn);
                    return;
                }
            }
        }    
        
        // 回调
        _func(conn);

    }

    void HandleSend(Connection* conn)
    {
        errno = 0;
        while(true)
        {
            ssize_t n = send(conn->GetSockfd(), conn->GetOutbuffer().c_str(),  conn->GetOutbuffer().size(), 0);
            if(n > 0)
            {
                conn->OutbufferRemove(n);
                if(conn->OutbufferEmpty())
                    break;
            }
            else if(n == 0)
            {
                return;
            }
            else
            {
                if(errno == EWOULDBLOCK || errno == EAGAIN)
                {
                    break;
                }
                else if(errno == EINTR)
                {
                    // 被信号中断
                    continue;
                }
                else
                {
                    conn->_excepter(conn);
                    return;
                }
            }
        }

        if(!conn->OutbufferEmpty())
        {
            // 打开读写关心
            conn->_R->EnableReadWrite(conn->GetSockfd(), true, true);
        }
        else
        {
            // 发完了就关闭对写事件的关心
            conn->_R->EnableReadWrite(conn->GetSockfd(), true, false);
        }
    }

    void HandleExcept(Connection* conn)
    {
        errno = 0;
        int fd = conn->GetSockfd();
        LOG(INFO, "client quit, fd = %d\n", fd);
        conn->_R->RemoveConnection(fd);
        // 由Reactor同一管理
    }

    func_t _func;
};